home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / misc / AmigaSDLsrc.lha / amisrc / SDL_blit.c < prev    next >
C/C++ Source or Header  |  2001-04-29  |  8KB  |  295 lines

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23. #ifdef SAVE_RCSID
  24. static char rcsid =
  25.  "@(#) $Id: SDL_blit.c,v 1.5.2.20 2001/02/10 21:21:31 hercules Exp $";
  26. #endif
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31.  
  32. #include "SDL_error.h"
  33. #include "SDL_video.h"
  34. #include "SDL_sysvideo.h"
  35. #include "SDL_blit.h"
  36. #include "SDL_RLEaccel_c.h"
  37. #include "SDL_pixels_c.h"
  38. #include "SDL_memops.h"
  39.  
  40. /* The general purpose software blit routine */
  41. static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
  42.             SDL_Surface *dst, SDL_Rect *dstrect)
  43. {
  44.     int okay;
  45.     int src_locked;
  46.     int dst_locked;
  47.  
  48.     /* Everything is okay at the beginning...  */
  49.     okay = 1;
  50.  
  51.     /* Lock the destination if it's in hardware */
  52.     dst_locked = 0;
  53.     if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  54.         SDL_VideoDevice *video = current_video;
  55.         SDL_VideoDevice *this  = current_video;
  56.         if ( video->LockHWSurface(this, dst) < 0 ) {
  57.             okay = 0;
  58.         } else {
  59.             dst_locked = 1;
  60.         }
  61.     }
  62.     /* Lock the source if it's in hardware */
  63.     src_locked = 0;
  64.     if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  65.         SDL_VideoDevice *video = current_video;
  66.         SDL_VideoDevice *this  = current_video;
  67.         if ( video->LockHWSurface(this, src) < 0 ) {
  68.             okay = 0;
  69.         } else {
  70.             src_locked = 1;
  71.         }
  72.     }
  73.  
  74.     /* Unencode the destination if it's RLE encoded */
  75.     if ( dst->flags & SDL_RLEACCEL ) {
  76.         SDL_UnRLESurface(dst, 1);
  77.         dst->flags |= SDL_RLEACCEL;    /* save accel'd state */
  78.     }
  79.  
  80.     /* Set up source and destination buffer pointers, and BLIT! */
  81.     if ( okay  && srcrect->w && srcrect->h ) {
  82.         SDL_BlitInfo info;
  83.         SDL_loblit RunBlit;
  84.  
  85.         /* Set up the blit information */
  86.         info.s_pixels = (Uint8 *)src->pixels + src->offset +
  87.                 (Uint16)srcrect->y*src->pitch +
  88.                 (Uint16)srcrect->x*src->format->BytesPerPixel;
  89.         info.s_width = srcrect->w;
  90.         info.s_height = srcrect->h;
  91.         info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
  92.         info.d_pixels = (Uint8 *)dst->pixels + dst->offset +
  93.                 (Uint16)dstrect->y*dst->pitch +
  94.                 (Uint16)dstrect->x*dst->format->BytesPerPixel;
  95.         info.d_width = dstrect->w;
  96.         info.d_height = dstrect->h;
  97.         info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
  98.         info.aux_data = src->map->sw_data->aux_data;
  99.         info.src = src->format;
  100.         info.table = src->map->table;
  101.         info.dst = dst->format;
  102.         RunBlit = src->map->sw_data->blit;
  103.  
  104.         /* Run the actual software blit */
  105.         RunBlit(&info);
  106.     }
  107.  
  108.     /* Re-encode the destination if it's RLE encoded */
  109.     if ( dst->flags & SDL_RLEACCEL ) {
  110.             dst->flags &= ~SDL_RLEACCEL; /* stop lying */
  111.         SDL_RLESurface(dst);
  112.     }
  113.  
  114.     /* We need to unlock the surfaces if they're locked */
  115.     if ( dst_locked ) {
  116.         SDL_VideoDevice *video = current_video;
  117.         SDL_VideoDevice *this  = current_video;
  118.         video->UnlockHWSurface(this, dst);
  119.     } else
  120.     if ( src_locked ) {
  121.         SDL_VideoDevice *video = current_video;
  122.         SDL_VideoDevice *this  = current_video;
  123.         video->UnlockHWSurface(this, src);
  124.     }
  125.     /* Blit is done! */
  126.     return(okay ? 0 : -1);
  127. }
  128.  
  129. static void SDL_BlitCopy(SDL_BlitInfo *info)
  130. {
  131.     Uint8 *src, *dst;
  132.     int w, h;
  133.     int srcskip, dstskip;
  134.  
  135.     w = info->d_width*info->dst->BytesPerPixel;
  136.     h = info->d_height;
  137.     src = info->s_pixels;
  138.     dst = info->d_pixels;
  139.     srcskip = w+info->s_skip;
  140.     dstskip = w+info->d_skip;
  141.     while ( h-- ) {
  142.         SDL_memcpy(dst, src, w);
  143.         src += srcskip;
  144.         dst += dstskip;
  145.     }
  146. }
  147.  
  148. static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
  149. {
  150.     Uint8 *src, *dst;
  151.     int w, h;
  152.     int srcskip, dstskip;
  153.  
  154.     w = info->d_width*info->dst->BytesPerPixel;
  155.     h = info->d_height;
  156.     src = info->s_pixels;
  157.     dst = info->d_pixels;
  158.     srcskip = w+info->s_skip;
  159.     dstskip = w+info->d_skip;
  160.     if ( dst < src ) {
  161.         while ( h-- ) {
  162.             SDL_memcpy(dst, src, w);
  163.             src += srcskip;
  164.             dst += dstskip;
  165.         }
  166.     } else {
  167.         src += ((h-1) * srcskip);
  168.         dst += ((h-1) * dstskip);
  169.         while ( h-- ) {
  170.             SDL_revcpy(dst, src, w);
  171.             src -= srcskip;
  172.             dst -= dstskip;
  173.         }
  174.     }
  175. }
  176.  
  177. /* Figure out which of many blit routines to set up on a surface */
  178. int SDL_CalculateBlit(SDL_Surface *surface)
  179. {
  180.     int blit_index;
  181.  
  182.     /* Clean everything out to start */
  183.     if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  184.         SDL_UnRLESurface(surface, 1);
  185.     }
  186.     surface->map->sw_blit = NULL;
  187.  
  188.     /* Figure out if an accelerated hardware blit is possible */
  189.     surface->flags &= ~SDL_HWACCEL;
  190.     if ( surface->map->identity ) {
  191.         int hw_blit_ok;
  192.  
  193.         if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  194.             /* We only support accelerated blitting to hardware */
  195.             if ( surface->map->dst->flags & SDL_HWSURFACE ) {
  196.                 hw_blit_ok = current_video->info.blit_hw;
  197.             } else {
  198.                 hw_blit_ok = 0;
  199.             }
  200.             if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
  201.                 hw_blit_ok = current_video->info.blit_hw_CC;
  202.             }
  203.             if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
  204.                 hw_blit_ok = current_video->info.blit_hw_A;
  205.             }
  206.         } else {
  207.             /* We only support accelerated blitting to hardware */
  208.             if ( surface->map->dst->flags & SDL_HWSURFACE ) {
  209.                 hw_blit_ok = current_video->info.blit_sw;
  210.             } else {
  211.                 hw_blit_ok = 0;
  212.             }
  213.             if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
  214.                 hw_blit_ok = current_video->info.blit_sw_CC;
  215.             }
  216.             if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
  217.                 hw_blit_ok = current_video->info.blit_sw_A;
  218.             }
  219.         }
  220.         if ( hw_blit_ok ) {
  221.             SDL_VideoDevice *video = current_video;
  222.             SDL_VideoDevice *this  = current_video;
  223.             video->CheckHWBlit(this, surface, surface->map->dst);
  224.         }
  225.     }
  226.  
  227.     /* Get the blit function index, based on surface mode */
  228.     /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
  229.     blit_index = 0;
  230.     blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY))      << 0;
  231.     if ( surface->flags & SDL_SRCALPHA
  232.          && (surface->format->alpha != SDL_ALPHA_OPAQUE
  233.          || surface->format->Amask) ) {
  234.             blit_index |= 2;
  235.     }
  236.  
  237.     /* Check for special "identity" case -- copy blit */
  238.     if ( surface->map->identity && blit_index == 0 ) {
  239.             surface->map->sw_data->blit = SDL_BlitCopy;
  240.  
  241.         /* Handle overlapping blits on the same surface */
  242.         if ( surface == surface->map->dst ) {
  243.                 surface->map->sw_data->blit = SDL_BlitCopyOverlap;
  244.         }
  245.     } else {
  246.         if ( surface->format->BitsPerPixel < 8 ) {
  247.             surface->map->sw_data->blit =
  248.                 SDL_CalculateBlit0(surface, blit_index);
  249.         } else {
  250.             switch ( surface->format->BytesPerPixel ) {
  251.                 case 1:
  252.                 surface->map->sw_data->blit =
  253.                     SDL_CalculateBlit1(surface, blit_index);
  254.                 break;
  255.                 case 2:
  256.                 case 3:
  257.                 case 4:
  258.                 surface->map->sw_data->blit =
  259.                     SDL_CalculateBlitN(surface, blit_index);
  260.                 break;
  261.                 default:
  262.                 surface->map->sw_data->blit = NULL;
  263.                 break;
  264.             }
  265.         }
  266.     }
  267.     /* Make sure we have a blit function */
  268.     if ( surface->map->sw_data->blit == NULL ) {
  269.         SDL_InvalidateMap(surface->map);
  270.         SDL_SetError("Blit combination not supported");
  271.         return(-1);
  272.     }
  273.  
  274.     /* Choose software blitting function */
  275.     if(surface->flags & SDL_RLEACCELOK
  276.        && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
  277.  
  278.             if(surface->map->identity
  279.            && (blit_index == 1
  280.                || (blit_index == 3 && !surface->format->Amask))) {
  281.                 if ( SDL_RLESurface(surface) == 0 )
  282.                     surface->map->sw_blit = SDL_RLEBlit;
  283.         } else if(blit_index == 2 && surface->format->Amask) {
  284.                 if ( SDL_RLESurface(surface) == 0 )
  285.                     surface->map->sw_blit = SDL_RLEAlphaBlit;
  286.         }
  287.     }
  288.     
  289.     if ( surface->map->sw_blit == NULL ) {
  290.         surface->map->sw_blit = SDL_SoftBlit;
  291.     }
  292.     return(0);
  293. }
  294.  
  295.